#!/usr/bin/env python3
from typing import Callable
from router import Router

from nicegui import ui
from ex4nicegui import rxui, to_ref, on, new_scope, __version__


# 装饰在函数上时，被装饰的函数会在每次执行时，自动销毁上一次运行中创建的响应式函数。
def with_scope(fn: Callable[..., None]):
    scope = new_scope()

    def wrapper(*args, **kwargs):
        nonlocal scope
        scope.dispose()
        scope = new_scope()
        return scope.run(lambda: fn(*args, **kwargs))

    return wrapper


# 数据类
class Model:
    def __init__(self):
        self.data = to_ref(0)

    def increment(self):
        self.data.value += 1


@ui.page("/")  # normal index page (e.g. the entry point of the app)
@ui.page(
    "/{_:path}"
)  # all other pages will be handled by the router but must be registered to also show the SPA index page
def main():
    router = Router()
    model = Model()

    @router.add("/")
    @with_scope
    def show_one():
        ui.label("Content One").classes("text-2xl")
        rxui.label(model.data).classes("text-2xl")

        # 如果没有使用 with_scope，则会打印很多次，跳转到这个页面多少次就会执行多少次，没有销毁？
        @on(model.data, onchanges=True)
        def on_data_changed():
            print("Data changed to", model.data.value)
            ui.notify(f"Data changed to {model.data.value}")

    @router.add("/two")
    def show_two():
        ui.label("Content Two").classes("text-2xl")
        # 改变数据
        ui.button("Increment", on_click=model.increment)

    @router.add("/three")
    def show_three():
        ui.label("Content Three").classes("text-2xl")

    ui.label(f"ex4ng 版本必须在 0.6.6或以上， 当前版本:{__version__}")
    ui.markdown(
        "下方来回点击 one two 按钮切换，如果没有在函数 `show_one` 中使用 `with_scope`，则会打印很多次，跳转到这个页面多少次就会执行多少次，没有销毁？"
    )

    # adding some navigation buttons to switch between the different pages
    with ui.row():
        ui.button("One", on_click=lambda: router.open(show_one)).classes("w-32")
        ui.button("Two", on_click=lambda: router.open(show_two)).classes("w-32")
        ui.button("Three", on_click=lambda: router.open(show_three)).classes("w-32")

    # this places the content which should be displayed
    router.frame().classes("w-full p-4 bg-gray-100")


ui.run()
